export namespace ColorHelper {
    export function HSVToRGB(hsv: [number, number, number]): [number, number, number] {
        let h = hsv[0];
        let s = hsv[1];
        let v = hsv[2];
        if (h == undefined || isNaN(h) || h < 0 || h > 360) {
            throw "H must be a number, greater than 0 and less than 360";
        }
        if (s == undefined || isNaN(s) || s < 0 || s > 100) {
            throw "S must be a number, greater than 0 and less than 100";
        }
        if (v == undefined || isNaN(v) || v < 0 || v > 100) {
            throw `V must be a number, greater than 0 and less than 100, ${v}`;
        }
        s = s / 100;
        v = v / 100;
        let c = v * s;
        let x = c * (1 - Math.abs((h / 60) % 2 - 1));
        let m = v - c;
        let _rgb = [];
        if (h >= 0 && h < 60) {
            _rgb = [c, x, 0];
        } else if (h >= 60 && h < 120) {
            _rgb = [x, c, 0];
        } else if (h >= 120 && h < 180) {
            _rgb = [0, c, x];
        } else if (h >= 180 && h < 240) {
            _rgb = [0, x, c];
        } else if (h >= 240 && h < 300) {
            _rgb = [x, 0, c];
        } else {
            _rgb = [c, 0, x];
        }
        return [Math.round((_rgb[0] + m) * 255), Math.round((_rgb[1] + m) * 255), Math.round((_rgb[2] + m) * 255)];
    }
    export function RGBToHSV(rgb: [number, number, number]): [number, number, number] {
        let r = rgb[0];
        let g = rgb[1];
        let b = rgb[2];
        (r == undefined || isNaN(r) || r > 255) && (r = 255);
        (r < 0) && (r = 0);
        (g == undefined || isNaN(g) || g > 255) && (g = 255);
        (g < 0) && (g = 0);
        (b == undefined || isNaN(b) || b > 255) && (b = 255);
        (b < 0) && (b = 0);
        let _r = r / 255;
        let _g = g / 255;
        let _b = b / 255;
        let cMax = Math.max(_r, _g, _b);
        let cMin = Math.min(_r, _g, _b);
        let x = cMax - cMin;
        let hsv = [];
        if (x == 0) {
            hsv[0] = 0;
        } else if (cMax == _r && _g >= _b) {
            hsv[0] = (x == 0 ? 0 : (60 * (_g - _b) / x));
        } else if (cMax == _r && _g < _b) {
            hsv[0] = (x == 0 ? 0 : (60 * (_g - _b) / x) + 360);
        } else if (cMax == _g) {
            hsv[0] = (x == 0 ? 0 : (60 * (((_b - _r) / x) + 2)));
        } else if (cMax == _b) {
            hsv[0] = (x == 0 ? 0 : (60 * (((_r - _g) / x) + 4)));
        }
        if (cMax == 0) {
            hsv[1] = 0;
        } else {
            hsv[1] = (cMax == 0 ? 0 : (x / cMax * 100));
        }
        hsv[2] = (cMax * 100);
        return <any>hsv;
    }
    export function HexToRGB(hex: string) {
        let _hex = [];
        hex = hex && hex.trim();
        if (hex.substring(0, 1) == "#") {
            hex = hex.substr(1, hex.length).replace(/\s*/g, "");
        } else {
            return [255, 255, 255, 1];
        }
        let arr1 = hex.split('');
        switch (hex.length) {
            case 0:
                return [255, 255, 255, 1];
            case 1:
                _hex = [hex + hex, hex + hex, hex + hex, "FF"];
                break;
            case 2:
                _hex = [hex, hex, hex, "FF"];
                break;
            case 3:
                _hex = [arr1[0] + arr1[0], arr1[1] + arr1[1], arr1[2] + arr1[2], "FF"];
                break;
            case 4:
                _hex = [arr1[0] + arr1[0], arr1[1] + arr1[1], arr1[2] + arr1[2], arr1[3] + arr1[3]];
                break;
            case 4:
                _hex = [arr1[0] + arr1[0], arr1[1] + arr1[1], arr1[2] + arr1[2], arr1[3] + arr1[3]];
                break;
            case 5:
                _hex = [arr1[0] + arr1[0], arr1[1] + arr1[1], arr1[2] + arr1[2], arr1[3] + arr1[4]];
                break;
            case 6:
                _hex = [arr1[0] + arr1[1], arr1[2] + arr1[3], arr1[4] + arr1[5], "FF"];
                break;
            case 7:
                _hex = [arr1[0] + arr1[1], arr1[2] + arr1[3], arr1[4] + arr1[5], arr1[6] + arr1[6]];
                break;
            default:
                _hex = [arr1[0] + arr1[1], arr1[2] + arr1[3], arr1[4] + arr1[5], arr1[6] + arr1[7]];
                break;
        }
        let r = parseInt("0x" + _hex[0]);
        r = isNaN(r) ? 255 : r;
        let g = parseInt("0x" + _hex[1]);
        g = isNaN(g) ? 255 : g;
        let b = parseInt("0x" + _hex[2]);
        b = isNaN(b) ? 255 : b;
        let a = parseInt("0x" + _hex[3]);
        a = isNaN(a) ? 1 : Number(Number(a / 255).toFixed(2));
        return [r, g, b, a];
    }
    export function RGBToHex(rgb: [number, number, number]) {
        let _rgb = (rgb instanceof Array) ? rgb : RGBToArray(rgb);
        let _hex = [];
        for (var x = 0; x < 3; x++) {
            let y = _rgb[x];
            if (isNaN(Number(y))) {
                _hex[x] = "FF";
            } else {
                let _y = Number(y).toString(16);
                _hex[x] = _y.length == 1 ? "0" + _y : _y;
            }
        }
        if (!isNaN(Number(_rgb[3]))) {
            let a = Math.floor(Number(_rgb[3]) * 255);
            if (a != 255) {
                let b = a.toString(16).toUpperCase();
                _hex[3] = b.length == 1 ? "0" + b : b;
            }
        }
        return _hex.join("").toUpperCase();
    }
    export function RGBToArray(rgb: string) {
        let _rgb = [];
        rgb = rgb && rgb.trim().toUpperCase();
        if (rgb.substring(0, 4) == "RGBA") {
            _rgb = rgb.replace("RGBA(", "").replace(")", "").replace(/\s*/g, "").split(",");
        } else if (rgb.substring(0, 3) == "RGB") {
            _rgb = rgb.replace("RGB(", "").replace(")", "").replace(/\s*/g, "").split(",");
        } else {
            _rgb = [255, 255, 255, 1];
        }
        return _rgb;
    }
}